/** ClientIO */
package client.io;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.text.ParseException;
import java.util.logging.Logger;

import org.json.JSONObject;

import domain.session.Request;
import domain.session.Response;

/**
 * Holds information regarding the client's connection to the server and
 * performs common I/O actions between the client and the server.
 * @author jessienewman
 * @version $Revision: 1.0 $
 */
public class ClientIO {
	
	/**
	 * Field LOGGER.
	 */
	private static final Logger LOGGER = Logger.getLogger(ClientIO.class.getName());
	
	/**
	 * Field SOCKET.
	 */
	private static Socket SOCKET; // $codepro.audit.disable initializeStaticFields

	/**
	 * Field OUT.
	 */
	private static Writer OUT; // $codepro.audit.disable initializeStaticFields
	
	/**
	 * Field IN.
	 */
	private static Reader IN; // $codepro.audit.disable initializeStaticFields
	
	/**
	 * Sets the connected Socket for the client.
	 * @param socket
	 */
	public static void setSocket(final Socket socket) {
		SOCKET = socket;
		try {
			//Store the writer and reader for this socket
			setWriter(new OutputStreamWriter(SOCKET.getOutputStream(), "ASCII"));
			setReader(new InputStreamReader(
					new BufferedInputStream(SOCKET.getInputStream())));
		} catch (final IOException ex) {
			LOGGER.info(ex.getMessage());
		} 
	}
	
	/**
	 * Sets the writer for the Socket.
	 * @param out
	 */
	public static void setWriter(final Writer out) {
		OUT = out;
	}
	
	/**
	 * Sets the reader for the Socket.
	 * @param in
	 */
	public static void setReader(final Reader in) {
		IN = in;
	}
	
	/**
	 * Write a given String to the server.
	 * @param s
	 */
	private static void write(String s) {
		try {
			OUT.write(s + "\r");
			OUT.flush();
		} catch (final IOException ex) {
			LOGGER.warning(ex.getMessage());
		}
	}
	
	/**
	 * Read a stream from the server and parse it into a JSONObject.
	
	 * @return JSONObject */
	private static JSONObject read() {
		String read = "";
		Boolean continueRun = true;
		try {
			while(continueRun) {
				int c = IN.read();
				if (c == '\r' || c == '\n' || c == -1) break;
				read += (char) c;
			}
		} catch (final IOException ex) {
			LOGGER.warning(ex.getMessage());
		}
		
		JSONObject json = null;
		
		try {
			json = new JSONObject(read);
		} catch (final ParseException ex) {
			LOGGER.warning(ex.getMessage());
		}
		
		return json;
	}
	
	/**
	 * Sends a Request to the server.
	 * @param request
	 */
	public static void sendRequest(final Request request) {
		if (request.toString() != null) {
			write(request.toString());
		} else {
			LOGGER.warning("Could not send request!");
		}
	}
	
	/**
	 * Waits for a response from the server and then returns it after
	 * it comes in.
	 * @return Response 
	 * */
	public static Response getResponse() {
		final Response response = new Response(read());
		return response;
	}
	
	/**
	 * returns the super's toString
	
	 * @return String super's toString */
	public String toString() {
		return super.toString();
	}
}
